home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dutil / libtos.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  7KB  |  348 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  LIBTOS.C
  9.  *
  10.  *  This program takes two arguments, AMIGA.LIB, and an OUTPUT FILE,
  11.  *  and systematically converts all references to the variables below
  12.  *  from ABSOLUTE to A4-RELATIVE (Using Lattice's DATA-REL16 relocation
  13.  *  info and symbol extensions).
  14.  *
  15.  *  It converts absolute move's into an A4 relative move and a nop to
  16.  *  take up the extra word which is now no longer used.
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #ifdef AMIGA
  23. #include <lib/version.h>
  24. #else
  25. #include <include/lib/version.h>
  26. #endif
  27.  
  28. IDENT("libtos",".4");
  29. DCOPYRIGHT;
  30.  
  31. short SymLens[64];
  32.  
  33. char *FixSymbols[64] = {
  34.     "_MathBase",
  35.     "_ClistBase",
  36.     "_ConsoleDevice",
  37.     "_DiskfontBase",
  38.     "_DOSBase",
  39.     "_SysBase",
  40.     "_GfxBase",
  41.     "_IconBase",
  42.     "_IntuitionBase",
  43.     "_LayersBase",
  44.     "_PotgoBase",
  45.     "_TimerBase",
  46.     "_TranslatorBase",
  47.     "_MathIeeeDoubBasBase",
  48.     "_MathTransBase",
  49.     "_ExpansionBase",
  50.     "_RomBootBase",
  51.     "_MathIeeeDoubTransBase",
  52.  
  53.     /*
  54.      *    2.0 stuff (doesn't effect anything if you
  55.      *           run on a 1.3 amiga.lib)
  56.      */
  57.  
  58.  
  59.     "_BattClockBase",
  60.     "_BattMemBase",
  61.     "_CxBase",
  62.     "_GadToolsBase",
  63.     "_KeymapBase",
  64.     "_MathIeeeSingBasBase",
  65.     "_MathIeeeSingTransBase",
  66.     "_UtilityBase",
  67.     "_WorkbenchBase",
  68.     "_MiscBase",
  69.     "_IFFParseBase",
  70.     "_InputBase",
  71.     "_AslBase",
  72.  
  73.     /*
  74.      *    3.0 stuff (doesn't effect anything if you
  75.      *           run on a 1.3 or 2.0 amiga.lib)
  76.      */
  77.  
  78.     "_AmigaGuideBase",
  79.     "_BulletBase",
  80.     "_ColorWheelBase",
  81.     "_DataTypesBase",
  82.     "_DiskBase",
  83.     "_DTClassBase",
  84.     "_LocaleBase",
  85.     "_RexxSysBase",
  86.  
  87.     NULL
  88. };
  89.  
  90. short DDebug;
  91. short Error;
  92.  
  93. typedef unsigned char ubyte;
  94. typedef unsigned short uword;
  95. typedef unsigned long ulong;
  96.  
  97. void InitSyms(void);
  98. int ScanRelocations(long, long *, char *, long, char *, int);
  99.  
  100. #define MAXHUNKS    32
  101.  
  102. int
  103. main(int ac, char **av)
  104. {
  105.     FILE *fi;
  106.     FILE *fo;
  107.     short hunkno;
  108.     long *base;
  109.     long *scan;
  110.     long *bend;
  111.     long bytes;
  112.  
  113.     InitSyms();
  114.     if (ac < 3) {
  115.         puts(Ident);
  116.         puts(DCopyright);
  117.     puts("libtos amiga.lib dlib:amigas.lib");
  118.     exit(1);
  119.     }
  120.     if (ac > 3)
  121.     DDebug = 1;
  122.     fi = fopen(av[1], "r");
  123.     if (fi == NULL) {
  124.     printf("couldn't open %s\n", av[1]);
  125.     exit(1);
  126.     }
  127.     fseek(fi, 0L, 2);
  128.     bytes = ftell(fi);
  129.     fseek(fi, 0L, 0);
  130.     base = malloc(bytes);
  131.     if (base == NULL) {
  132.     puts("ran out of memory");
  133.     exit(1);
  134.     }
  135.     fread((char *)base, bytes, 1, fi);
  136.     fclose(fi);
  137.     bend = base + (bytes >> 2);
  138.  
  139.     for (scan = base; scan < bend;) {
  140.     ubyte *data;
  141.     long dlen;
  142.     short htype;
  143.  
  144.     hunkno = 0;
  145.     if (*scan != 0x3E7) {
  146.         printf("Expected hunk_unit, got %08lx\n", *scan);
  147.         exit(1);
  148.     }
  149.     scan += scan[1] + 2;
  150.  
  151.     /*
  152.      *  scan the object module
  153.      */
  154.  
  155.     data = NULL;
  156.     dlen = 0;
  157.     htype = 0;
  158.  
  159.     while (scan < bend && *scan != 0x3E7) {
  160.         ulong len;
  161.  
  162.         switch((uword)*scan) {
  163.         case 0x3E8:         /*    HUNK_NAME    */
  164.         scan += scan[1] + 2;
  165.         break;
  166.         case 0x3E9:         /*    HUNK_CODE    */
  167.         case 0x3EA:         /*    HUNK_DATA    */
  168.         data = (char *)(scan + 2);
  169.         dlen = scan[1] << 2;
  170.         if (*scan == 0x3EA)
  171.             htype = 1;
  172.         else
  173.             htype = 2;
  174.  
  175.         {
  176.             ++hunkno;
  177.         }
  178.         scan += scan[1] + 2;
  179.         break;
  180.         case 0x3EB:         /*    HUNK_BSS    */
  181.         htype = 0;
  182.         scan += 2;
  183.         break;
  184.         case 0x3EC:         /*    HUNK_RELOC32    */
  185.         case 0x3ED:         /*    HUNK_RELOC16-PC */
  186.         case 0x3EE:         /*    HUNK_RELOC8    */
  187.         case 0x3F8:         /*    HUNK_RELOC16-D    (special) */
  188.         ++scan;
  189.         while (*scan)
  190.             scan += *scan + 2;
  191.         ++scan;
  192.         break;
  193.         case 0x3EF:         /*    HUNK_EXT    */
  194.         case 0x3F0:         /*    HUNK_SYMBOL    */
  195.         ++scan;
  196.         while ((len = *scan) != 0) {
  197.             ubyte type = len >> 24;
  198.             long *base = scan;
  199.  
  200.             len &= 0x00FFFFFF;
  201.             if (DDebug)
  202.             printf("extsym %3d %.*s\n", type, (int)(len*4), (char *)(scan + 1));
  203.             scan += len + 1;
  204.  
  205.             switch(type) {
  206.             case 0:        /*    SYMB    */
  207.             case 1:        /*    DEF    */
  208.             case 2:        /*    ABS    */
  209.             case 3:        /*    RES    */
  210.             ++scan;     /*    skip value  */
  211.             break;
  212.             case 130:        /*    COMMON    */
  213.             ++scan;     /*    skip common size */
  214.             /* fall through */
  215.             case 129:        /*    REF32    */
  216.             if (type == 129 && htype == 2) {
  217.                 if (ScanRelocations(scan[0], scan + 1, data, dlen, (char *)(base + 1), len*4))
  218.                 *base = (*base & 0x00FFFFFF) | (134 << 24);    /*  convert from ABS32 to DATA-REL16    */
  219.             }
  220.             case 131:        /*    REF16    */
  221.             case 132:        /*    REF8    */
  222.             case 134:        /*    REF16D    */
  223.                     /*    skip relocation info */
  224.             scan += scan[0] + 1;
  225.             break;
  226.             default:
  227.             printf("Symbol type %d unknown", type);
  228.             exit(1);
  229.             }
  230.         }
  231.         ++scan;     /*    skip 0 terminator */
  232.         break;
  233.         case 0x3F1:         /*    HUNK_DEBUG        */
  234.         scan += scan[1] + 2;
  235.         break;
  236.         case 0x3F2:         /*    HUNK_END        */
  237.         data = NULL;
  238.         dlen = 0;
  239.         ++hunkno;
  240.         ++scan;
  241.         break;
  242.         default:
  243.         printf("Unknown hunk type $%08lx", *scan);
  244.         exit(1);
  245.         }
  246.     }
  247.     }
  248.  
  249.     if (Error) {
  250.     puts("ERROR OCCURED, OUTPUT NOT WRITTEN");
  251.     return(1);
  252.     }
  253.  
  254.     fo = fopen(av[2], "w");
  255.     if (fo == NULL) {
  256.     printf("couldn't create %s\n", av[2]);
  257.     return(1);
  258.     }
  259.     fwrite((char *)base, bytes, 1, fo);
  260.     fclose(fo);
  261.     return(0);
  262. }
  263.  
  264. void
  265. InitSyms()
  266. {
  267.     short i;
  268.     for (i = 0; FixSymbols[i]; ++i) {
  269.     SymLens[i] = strlen(FixSymbols[i]);
  270.     }
  271. }
  272.  
  273. int
  274. ScanRelocations(entries, scan, data, dlen, name, len)
  275. long entries;
  276. long *scan;
  277. char *data;
  278. long dlen;
  279. char *name;
  280. int len;
  281. {
  282.  
  283.     printf("Relocation: %2ld relocations for symbol %-20.*s", entries, len, name);
  284.  
  285.     {
  286.     short i;
  287.     static char Buf[256];
  288.  
  289.     strncpy(Buf, name, len);
  290.     Buf[len] = 0;
  291.  
  292.     for (i = 0; SymLens[i]; ++i) {
  293.         if (strcmp(FixSymbols[i], Buf) == 0)
  294.         break;
  295.     }
  296.     if (SymLens[i] == 0) {
  297.         printf("(%s %d not modified)\n", Buf, strlen(Buf));
  298.         return(0);
  299.     }
  300.     }
  301.     puts("(modifying)");
  302.  
  303.     while (entries) {
  304.     long index = *scan;
  305.     uword *tscan;
  306.     uword opcode;
  307.  
  308.     if (index < 0 || index > dlen - 4) {
  309.         printf("relocation index out of range: %ld/%ld\n", index, dlen);
  310.         Error = 1;
  311.     }
  312.     tscan = (uword *)(data + index - 2);
  313.  
  314.     opcode = *tscan;
  315.     printf("\topcode %04x\n", opcode);
  316.  
  317.     /*
  318.      *  convert abs to off(A4)  0010 0000 0110 1100
  319.      */
  320.  
  321.     switch(opcode) {
  322.     case 0x2079:    /*  move.l  abslong,A0    */
  323.         tscan[0] = 0x206C;
  324.         tscan[1] = tscan[2];
  325.         tscan[2] = 0x4E71;
  326.         break;
  327.     case 0x2C79:    /*  move.l  abslong,A6    */
  328.         tscan[0] = 0x2C6C;
  329.         tscan[1] = tscan[2];
  330.         tscan[2] = 0x4E71;
  331.         break;
  332.     case 0xD1F9:    /*  adda.l  abslong,A0    */
  333.         tscan[0] = 0xD1EC;
  334.         tscan[1] = tscan[2];
  335.         tscan[2] = 0x4E71;
  336.         break;
  337.     default:
  338.         printf("\tWarning, opcode not understood, could not modify\n");
  339.         Error = 1;
  340.         break;
  341.     }
  342.     ++scan;
  343.     --entries;
  344.     }
  345.     return(1);
  346. }
  347.  
  348.